import re
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

# 设置matplotlib以正确显示中文字符
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


def parse_log_with_atr_mae(file_path):
    """
    解析包含ATR和MAE信息的新版日志文件。
    """
    try:
        with open(file_path, 'r', encoding='UTF-8') as f:
            content = f.read()
    except FileNotFoundError:
        print(f"错误：找不到文件 {file_path}")
        return None

    blocks = content.split('=========\n')

    open_positions = {}
    completed_trades = []

    # 更新后的正则表达式
    id_pattern = re.compile(r"├─ 仓位ID : ([\w-]+)")
    symbol_pattern = re.compile(r"├─ 交易品种: (\S+)")
    open_reason_pattern = re.compile(r"atr: ([\d.]+), .*")
    close_reason_pattern = re.compile(r"平仓原因: .*MAE: ([\d.]+)%")
    pnl_pattern = re.compile(r"├─ 本笔盈亏: ([-\d.]+)")
    entry_price_pattern = re.compile(r"开仓 ([\d.]+)")

    for block in blocks:
        id_match = id_pattern.search(block)
        if not id_match: continue
        position_id = id_match.group(1)

        if "[开仓做" in block:
            symbol_match = symbol_pattern.search(block)
            reason_match = open_reason_pattern.search(block)
            if symbol_match and reason_match:
                open_positions[position_id] = {
                    'symbol': symbol_match.group(1),
                    'atr_at_open': float(reason_match.group(1))
                }

        elif "[平仓" in block or "[止损" in block:
            if position_id in open_positions:
                pnl_match = pnl_pattern.search(block)
                reason_match = close_reason_pattern.search(block)
                entry_price_match = entry_price_pattern.search(block)

                if pnl_match and reason_match and entry_price_match:
                    trade_data = open_positions.pop(position_id)
                    trade_data['pnl'] = float(pnl_match.group(1))

                    mae_percentage = float(reason_match.group(1))
                    trade_data['mae_percent'] = mae_percentage

                    entry_price = float(entry_price_match.group(1))

                    # --- 核心计算：将MAE从百分比转换为ATR的倍数 ---
                    # MAE的绝对价格变动 = MAE百分比 * 开仓价
                    mae_in_price = (mae_percentage / 100.0) * entry_price

                    # MAE是ATR的几倍 = MAE的绝对价格变动 / 开仓时的ATR值
                    if trade_data['atr_at_open'] > 0:
                        mae_in_atr = mae_in_price / trade_data['atr_at_open']
                        trade_data['mae_in_atr'] = mae_in_atr
                    else:
                        trade_data['mae_in_atr'] = np.nan

                    completed_trades.append(trade_data)

    if not completed_trades:
        print("警告：未能解析出任何完整交易。")
        return pd.DataFrame()

    df = pd.DataFrame(completed_trades)
    df.dropna(subset=['mae_in_atr'], inplace=True)
    return df


def analyze_mae_in_atr(df):
    """
    对 MAE_in_ATR 进行深度分析和可视化。
    """
    if df.empty or 'mae_in_atr' not in df.columns:
        print("数据不足，无法分析。")
        return

    df['盈利情况'] = np.where(df['pnl'] > 0, '盈利', '亏损')

    # --- 1. 核心统计数据 ---
    print("\n--- MAE (以ATR倍数计) 的核心统计 ---")
    mae_atr_stats = df.groupby('盈利情况')['mae_in_atr'].describe()
    print(mae_atr_stats)

    winning_trades_mae_atr = df[df['盈利情况'] == '盈利']['mae_in_atr']
    print("\n--- 盈利交易的 MAE_in_ATR 百分位数 (ATR止损倍数N的参考) ---")
    if not winning_trades_mae_atr.empty:
        q50 = winning_trades_mae_atr.quantile(0.50)
        q80 = winning_trades_mae_atr.quantile(0.80)
        q95 = winning_trades_mae_atr.quantile(0.95)
        print(f"50% (中位数): {q50:.2f} 倍ATR")
        print(f"80% 的盈利交易其回撤小于: {q80:.2f} 倍ATR")
        print(f"95% 的盈利交易其回撤小于: {q95:.2f} 倍ATR")
        print("\n==> 结论: 一个相对安全的ATR止损倍数 N 应该大于 " f"{q80:.2f}，例如可以选择 {np.ceil(q80 * 10) / 10} 或更高。")

    # --- 2. 可视化分析 ---
    fig, axes = plt.subplots(1, 2, figsize=(20, 8))
    fig.suptitle('ATR动态止损分析：寻找最优止损倍数N', fontsize=20, y=1.03)

    # 图1: 盈利交易的MAE_in_ATR分布 (最重要的图)
    sns.histplot(data=winning_trades_mae_atr, ax=axes[0], kde=True, bins=30, color='darkgreen')
    axes[0].axvline(q80, color='orange', linestyle='--', linewidth=2.5, label=f'80%分位点: {q80:.2f}x ATR')
    axes[0].axvline(q95, color='red', linestyle='--', linewidth=2.5, label=f'95%分位点: {q95:.2f}x ATR')
    axes[0].set_title('盈利交易所必需的“呼吸空间” (以ATR倍数计)', fontsize=16)
    axes[0].set_xlabel('最大不利变动 (MAE) 是开仓时ATR的几倍 (N)')
    axes[0].set_ylabel('交易次数')
    axes[0].legend()
    axes[0].grid(True)

    # 图2: 盈利 vs 亏损交易的MAE_in_ATR分布对比
    sns.boxplot(data=df, x='盈利情况', y='mae_in_atr', ax=axes[1], order=['盈利', '亏损'])
    sns.stripplot(data=df, x='盈利情况', y='mae_in_atr', ax=axes[1], alpha=0.3, color='black', order=['盈利', '亏损'])
    axes[1].set_title('盈利 vs 亏损交易的MAE_in_ATR分布', fontsize=16)
    axes[1].set_xlabel('交易结果')
    axes[1].set_ylabel('最大不利变动 (MAE) / ATR')
    axes[1].grid(axis='y')

    plt.tight_layout()
    plt.show()


# --- 主程序 ---
if __name__ == "__main__":
    file_path = '回测结果 (2).txt'
    trades_df = parse_log_with_atr_mae(file_path)

    if trades_df is not None and not trades_df.empty:
        analyze_mae_in_atr(trades_df)
    else:
        print("未能加载或解析数据，分析终止。")